package org.jeecg.modules.product.risk.thread;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.CommonAPI;
import org.jeecg.common.util.UUIDGenerator;
import org.jeecg.modules.product.holidaysEstivals.entity.TbHolidaysEstivals;
import org.jeecg.modules.product.holidaysEstivals.mapper.TbHolidaysEstivalsMapper;
import org.jeecg.modules.product.risk.entity.TbBaseControlMeasures;
import org.jeecg.modules.product.risk.entity.TbBaseMeasuresTask;
import org.jeecg.modules.product.risk.entity.TbBaseMeasuresTaskRecord;
import org.jeecg.modules.product.risk.entity.TbBaseRiskEvents;
import org.jeecg.modules.product.risk.mapper.TbBaseControlMeasuresMapper;
import org.jeecg.modules.product.risk.mapper.TbBaseMeasuresTaskMapper;
import org.jeecg.modules.product.risk.mapper.TbBaseMeasuresTaskRecordMapper;
import org.jeecg.modules.product.risk.mapper.TbBaseRiskEventsMapper;
import org.jeecg.modules.product.risk.service.ITbBaseMeasuresTaskRecordService;
import org.jeecg.modules.product.risk.service.ITbBaseMeasuresTaskService;
import org.jeecg.modules.product.until.ApplicationContextProvider;
import org.jeecgframework.core.util.ApplicationContextUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationContextFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.web.servlet.view.tiles3.SpringBeanPreparerFactory;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
public class TaskDerivationThread implements Runnable{

    private TbBaseRiskEventsMapper tbBaseRiskEventsMapper = ApplicationContextProvider.getBean(TbBaseRiskEventsMapper.class);
    private TbBaseControlMeasuresMapper tbBaseControlMeasuresMapper = ApplicationContextProvider.getBean(TbBaseControlMeasuresMapper.class);
    private ITbBaseMeasuresTaskService tbBaseMeasuresTaskService = ApplicationContextProvider.getBean(ITbBaseMeasuresTaskService.class);
    private ITbBaseMeasuresTaskRecordService tbBaseMeasuresTaskRecordService = ApplicationContextProvider.getBean(ITbBaseMeasuresTaskRecordService.class);
    private TbHolidaysEstivalsMapper tbHolidaysEstivalsMapper = ApplicationContextProvider.getBean(TbHolidaysEstivalsMapper.class);
    private CommonAPI commonAPI = ApplicationContextProvider.getBean(CommonAPI.class);
    private List<TbBaseRiskEvents> eventsList = null;
    private List<TbBaseControlMeasures> measuresList = null;
    private List<TbBaseMeasuresTask> taskList = null;
    private List<TbBaseMeasuresTask> updateTaskList =  new ArrayList<>();
    private List<TbBaseMeasuresTaskRecord> taskRecordList = new ArrayList<>();
    private List<String> holidaysEstivalsStrList = null;
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    private SimpleDateFormat sdfTime = new SimpleDateFormat("HH:mm:00");
    private SimpleDateFormat sdfHH = new SimpleDateFormat("yyyy-MM-dd HH");

    @Override
    public void run() {
        //查询到所有任务
        eventsList = tbBaseRiskEventsMapper.selectList(new QueryWrapper<TbBaseRiskEvents>().eq("deleted","0"));
        measuresList = tbBaseControlMeasuresMapper.selectList(new QueryWrapper<TbBaseControlMeasures>().eq("deleted","0"));
        taskList = tbBaseMeasuresTaskService.list(new QueryWrapper<TbBaseMeasuresTask>().eq("deleted","0"));
        holidaysEstivalsStrList = tbHolidaysEstivalsMapper.selectCurrYearStrList();
        if (!taskList.isEmpty()){
            try {
                Date currDate = new Date();
                String currStrTime = sdfTime.format(currDate);
                String currStrDate = sdf.format(currDate);
                boolean holidaysFlag =  holidaysEstivalsStrList.stream().anyMatch(item -> item.equals(currStrDate));
                for (TbBaseMeasuresTask task : taskList) {
                    //step.1比较任务开始时间和当前时间，开始时间在当前时间之前或者相等再下一步
                    int comparison = task.getStartTime().compareTo(currDate);
                    if(comparison <= 0){
                        boolean flag = determineDateType(task.getCalendar(),holidaysFlag,currDate,currStrTime,task);

                        log.info("------flag---------------------"+flag);
                        if(flag){//如果时间日期符合就开始指派任务
                            task = computeLatestTime(task);
                            /*这快的逻辑意思就是即使更新任务模版信息中最近一个任务下发时间，并根据该时间和当前时间做比较，
                            如果该时间小于等于当前时间，表示已经满足周期，则下发任务。如果大于则周期不满，则不下发任务*/
                            //如果不是空表示已经有在执行的任务了，所以加周期判定
                            if(null !=task.getLatestTime()){
                                if(task.getLatestTime().compareTo(currDate) <= 0){
                                    task.setLatestTime(currDate);
                                    addTaskRecord(task,currDate);
                                }
                            }else {//为空直接执行
                                addTaskRecord(task,currDate);
                            }
                        }
                    }
                }
            }catch (Exception e){
                log.error("风险任务初始化引擎异常-----------"+e);
            }
        }
        if (!taskRecordList.isEmpty()){
            tbBaseMeasuresTaskRecordService.saveBatch(taskRecordList);
            log.info("----增加的风险任务条数为------------"+taskRecordList.size());
            taskRecordList.clear();
        }
        if (!updateTaskList.isEmpty()){
            tbBaseMeasuresTaskService.updateBatchById(updateTaskList);
            log.info("----更新的任务模版衍生时间条数为------------"+updateTaskList.size());
            updateTaskList.clear();
        }
    }

    /*增加线程锁，保证数据的一致性*/
    public synchronized void addTaskRecord(TbBaseMeasuresTask task,Date currDate){
        TbBaseMeasuresTaskRecord taskRecord = new TbBaseMeasuresTaskRecord();
        //管控措施不为空，并且没有被删除的管控措施才会被配置任务
        Optional<TbBaseControlMeasures> optional = measuresList.stream().filter(item ->item.getId().equals(task.getRiskMeasureId())).findAny();
        if (optional.isPresent()){
            TbBaseControlMeasures baseControlMeasures = optional.get();
            String eventId = baseControlMeasures.getRiskEventId();

            Optional<TbBaseRiskEvents> optionalEvent = eventsList.stream().filter(item ->item.getId().equals(eventId)).findAny();
            if (optionalEvent.isPresent()){
                TbBaseRiskEvents events = optionalEvent.get();

                taskRecord.setId(UUIDGenerator.generate());
                //创建人
                taskRecord.setCreateBy(baseControlMeasures.getCreateBy());
                //归属部门
                taskRecord.setSysOrgCode(baseControlMeasures.getSysOrgCode());
                //管控措施
                taskRecord.setRiskMeasureDesc(baseControlMeasures.getRiskMeasureDesc());
                //排查内容
                taskRecord.setTroubleshootOntent(baseControlMeasures.getTroubleshootContent());
                //周期
                taskRecord.setPeriod(task.getPeriod());
                //周期单位
                taskRecord.setPeriodUnit(task.getPeriodUnit());
                taskRecord.setTaskStartTime(currDate);
                taskRecord.setTaskEndTime(computeTaskEndTime(taskRecord));
                //未巡检
                taskRecord.setCheckStatus("2");
                //装置
                taskRecord.setRiskDeviceId(events.getRiskDeviceId());
                //单元
                taskRecord.setRiskUnitId(events.getRiskUnitId());
                //正常
                taskRecord.setDeleted("0");
                //任务id
                taskRecord.setCheckTaskId(task.getId());
                //先写死
                taskRecord.setCreateByMobile("13212254211");
                /*任务类型,是否是是否包保责任人任务*/
                if ("0".equals(task.getWorkType())) {
                    taskRecord.setIsDefend("0");
                } else {
                    taskRecord.setIsDefend("1");
                }
                /*排查人员*/
                taskRecord.setIdentifyPeople(task.getIdentifyPeople());
                /*这块可以注释掉了，因为已经在选择岗位的时候已经将岗位对应的人员加到任务上的排查人员上了*/
//                if("distributionType01".equals(task.getType())){
//                    taskRecord.setIdentifyPeople(task.getIdentifyPeople());
//                }else if ("distributionType02".equals(task.getType())){
//                    List<String> userNameList = commonAPI.getUserNameListByPositionId(task.getIdentifyStation());
//                    if (!userNameList.isEmpty()){
//                        taskRecord.setIdentifyPeople(userNameList.toString());
//                    }
//                }
                taskRecordList.add(taskRecord);
                //更新任务模版中最近一次任务衍生时间
                task.setLatestTime(null == task.getLatestTime() ? currDate :task.getLatestTime());
                updateTaskList.add(task);
            }
        }
    }

    public Date computeTaskEndTime(TbBaseMeasuresTaskRecord taskRecord){
        Calendar calendar = Calendar.getInstance();
        /*计算最一次任务下发时间*/
        if("periodType01".equals(taskRecord.getPeriodUnit())){//小时
            /*为空表示任务第一次执行，不为空则更新*/
            calendar.setTime(taskRecord.getTaskStartTime());
            calendar.add(Calendar.HOUR,taskRecord.getPeriod());
            taskRecord.setTaskEndTime(calendar.getTime());
        } else if ("periodType02".equals(taskRecord.getPeriodUnit())) {//天
            /*为空表示任务第一次执行，不为空则更新*/
            calendar.setTime(taskRecord.getTaskStartTime());
            calendar.add(Calendar.DATE,taskRecord.getPeriod());
            taskRecord.setTaskEndTime(calendar.getTime());
        } else if ("periodType03".equals(taskRecord.getPeriodUnit())) {//月
            /*为空表示任务第一次执行，不为空则更新*/
            calendar.setTime(taskRecord.getTaskStartTime());
            calendar.add(Calendar.MONTH,taskRecord.getPeriod());
            taskRecord.setTaskEndTime(calendar.getTime());
        } else if ("periodType04".equals(taskRecord.getPeriodUnit())) {//年
            /*为空表示任务第一次执行，不为空则更新*/
            calendar.setTime(taskRecord.getTaskStartTime());
            calendar.add(Calendar.YEAR,taskRecord.getPeriod());
            taskRecord.setTaskEndTime(calendar.getTime());
        }
        return taskRecord.getTaskEndTime();
    }

    public TbBaseMeasuresTask computeLatestTime(TbBaseMeasuresTask task){
        Calendar calendar = Calendar.getInstance();
        log.info("------taskId---------------------"+task.getId());
        /*计算最一次任务下发时间*/
        if("periodType01".equals(task.getPeriodUnit())){//小时
            /*为空表示任务第一次执行，不为空则更新*/
            if(null != task.getLatestTime()){
                calendar.setTime(task.getLatestTime());
                calendar.add(Calendar.HOUR,task.getPeriod());
                task.setLatestTime(calendar.getTime());
            }
        } else if ("periodType02".equals(task.getPeriodUnit())) {//天
            /*为空表示任务第一次执行，不为空则更新*/
            if(null != task.getLatestTime()){
                calendar.setTime(task.getLatestTime());
                calendar.add(Calendar.DATE,task.getPeriod());
                task.setLatestTime(calendar.getTime());
            }
        } else if ("periodType03".equals(task.getPeriodUnit())) {//月
            /*为空表示任务第一次执行，不为空则更新*/
            if(null != task.getLatestTime()){
                calendar.setTime(task.getLatestTime());
                calendar.add(Calendar.MONTH,task.getPeriod());
                task.setLatestTime(calendar.getTime());
            }
        } else if ("periodType04".equals(task.getPeriodUnit())) {//年
            /*为空表示任务第一次执行，不为空则更新*/
            if(null != task.getLatestTime()){
                calendar.setTime(task.getLatestTime());
                calendar.add(Calendar.YEAR,task.getPeriod());
                task.setLatestTime(calendar.getTime());
            }
        }
        return task;
    }

    public boolean determineDateType(String calendarType,boolean holidaysFlag,Date currDate, String currStrTime,TbBaseMeasuresTask task){
        //返回状态
        boolean determineDateTypeFlag = false;
        try {
            if ("calendarType01".equals(calendarType)) {//每天xx
                if ("periodType01".equals(task.getPeriodUnit())) {//小时
                    /*如果开始时间在结束时间之前*/
                    if(task.getWorkBeginTime().compareTo(task.getWorkEndTime()) <0){
                        if (currStrTime.compareTo(task.getWorkBeginTime()) >= 0  && currStrTime.compareTo(task.getWorkEndTime()) < 0) {//如果工作时间在当前时间之前就需要添加
                            determineDateTypeFlag = true;
                        }
                    }else if (task.getWorkBeginTime().compareTo(task.getWorkEndTime()) == 0){
                        determineDateTypeFlag = true;
                    }
                } else if ("periodType02".equals(task.getPeriodUnit())) {//天
                    determineDateTypeFlag = true;
                } else if ("periodType03".equals(task.getPeriodUnit())) {//月
                    determineDateTypeFlag = true;
                } else if ("periodType04".equals(task.getPeriodUnit())) {//年
                    determineDateTypeFlag = true;
                }
            } else if ("calendarType02".equals(calendarType)) {//工作日
                if(!holidaysFlag){
                    if ("periodType01".equals(task.getPeriodUnit())) {//小时
                        if(task.getWorkBeginTime().compareTo(task.getWorkEndTime()) < 0){
                            if (currStrTime.compareTo(task.getWorkBeginTime()) < 0  && currStrTime.compareTo(task.getWorkEndTime()) >0) {//如果工作时间在当前时间之前就需要添加
                                determineDateTypeFlag = true;
                            }
                        }else if (task.getWorkBeginTime().compareTo(task.getWorkEndTime()) == 0){
                            determineDateTypeFlag = true;
                        }
                    } else if ("periodType02".equals(task.getPeriodUnit())) {//天
                        determineDateTypeFlag = true;
                    }
                }
            } else if ("calendarType03".equals(calendarType)) {//非工作日
                if(holidaysFlag){
                    if ("periodType01".equals(task.getPeriodUnit())) {//小时
                        if(task.getWorkBeginTime().compareTo(task.getWorkEndTime()) < 0){
                            if (currStrTime.compareTo(task.getWorkBeginTime()) < 0  && currStrTime.compareTo(task.getWorkEndTime()) >0) {//如果工作时间在当前时间之前就需要添加
                                determineDateTypeFlag = true;
                            }
                        }else if (task.getWorkBeginTime().compareTo(task.getWorkEndTime()) == 0){
                            determineDateTypeFlag = true;
                        }
                    } else if ("periodType02".equals(task.getPeriodUnit())) {//天
                        determineDateTypeFlag = true;
                    }
                }
            }
        }catch (Exception e){
            log.error("日期比较异常-----------"+e);
        }
        return determineDateTypeFlag;
    }
}
